package vn.wallet.app.dao.impl;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;

import vn.wallet.app.dao.CommonInterfaceDAO;

public abstract class GenericDAO<T> implements CommonInterfaceDAO<T> {

	@Resource
	private SessionFactory sessionFactory;

	private final Class<T> entityClass;

	public GenericDAO(Class<T> entityClass) {
		this.entityClass = entityClass;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T getById(final int id) throws Exception {
		return (T) getSessionFactory().getCurrentSession().get(entityClass, id);
	}

	@Override
	public void save(T obj) throws Exception {
		sessionFactory.getCurrentSession().persist(obj);
	};

	@Override
	public void update(T obj) throws Exception {
		sessionFactory.getCurrentSession().merge(obj);
	};

	@Override
	public void delete(T obj) throws Exception {
		sessionFactory.getCurrentSession().delete(obj);
	};

	@Override
	public void delete(int id) throws Exception {
		sessionFactory.getCurrentSession().delete(getById(id));
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> getAll() throws Exception {
		Criteria crit = sessionFactory.getCurrentSession().createCriteria(entityClass);
		return crit.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> getAllByUserId(int userId) throws Exception {
		Query query = sessionFactory.getCurrentSession().createQuery("from " + entityClass.getName() + " where user_id = :user_id");
		query.setParameter("user_id", userId);

		return query.list();
	}

	@Override
	public int getCount() throws Exception {
		String strQuery = "select count(*) from " + entityClass.toString();
		return (Integer) sessionFactory.getCurrentSession().createQuery(strQuery).uniqueResult();

	}

	@SuppressWarnings("rawtypes")
	public List executeQuery(String hql) {
		return sessionFactory.getCurrentSession().createQuery(hql).list();
	}

	@SuppressWarnings("rawtypes")
	public List executeQuery(String hql, Map<String, Object> parameters) {
		Query query = sessionFactory.getCurrentSession().createQuery(hql);

		Iterator<String> keys = parameters.keySet().iterator();
		while (keys.hasNext()) {
			String paramsName = keys.next();
			query.setParameter(paramsName, parameters.get(paramsName));
		}
		return query.list();
	}

	@SuppressWarnings("rawtypes")
	public List executeQuery(String hql, String paramName, Object obj) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(paramName, obj);

		return executeQuery(hql, map);
	}

	// --------------properties
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
}
